using System;
using System.Collections.Generic;
using System.Linq;
using SharpDropBoxClient;

namespace System.IO.DropBox
{
    public class DBXDirectory
    {
        private static IDropBoxSetup _DropBoxSetupObject = DropBoxSetup.Instance;

        public static IDropBoxSetup DropBoxSetupObject
        {
            get
            {
                return _DropBoxSetupObject;
            }
            set
            {
                _DropBoxSetupObject = value;
                DBXFile.setDropBoxSetupObjectFromDirectory(value);
            }
        }

        internal static void setDropBoxSetupObjectFromFile(IDropBoxSetup dropBoxSetupObject)
        {
            _DropBoxSetupObject = dropBoxSetupObject;
        }

        private static IDropBoxApp DbxApp
        {
            get
            {
                if (DropBoxSetupObject == null)
                    return null;
                return DropBoxSetupObject.DropBoxApp;
            }
        }

        private static bool EnsureDbxAppHasInstance(Action<Exception> errorCallback)
        {
            if (DbxApp == null)
            {
                errorCallback(new IOException("You need to configure the DropBoxSetup object first"));
                return false;
            }
            return true;
        }

        public static void CreateDirectoryAsync(string path, Action<DBXDirectoryInfo, Exception> callback)
        {
            if (EnsureDbxAppHasInstance((ex) => callback(null, ex)))
            {
                DbxApp.CreateDirectory(path, (info) =>
                {
                    if (info.Error != null)
                    {
                        callback(null, info.Error);
                    }
                    else
                    {
                        callback(new DBXDirectoryInfo(path), null);
                    }
                });
            }
        }

        public static void DeleteAsync(string path, Action<Exception> callback)
        {
            if (EnsureDbxAppHasInstance(callback))
            {
                DbxApp.DeletePathOrFile(path, (ex) =>
                    {
                        callback(ex);
                    });
            }
        }

        public static void DeleteAsync(string path, bool recursive, Action<Exception> callback)
        {
            if (!recursive)
            {
                callback(new IOException("Deletes are always recursive in DropBox"));
                return;
            }
            if (EnsureDbxAppHasInstance(callback))
            {
                DbxApp.DeletePathOrFile(path, (ex) =>
                {
                    callback(ex);
                });
            }
        }

        public static void ExistsAsync(string path, Action<bool, Exception> callback)
        {
            if (EnsureDbxAppHasInstance((ex) => callback(false, ex)))
            {
                DbxApp.GetFileEntry(path, new List<string>(), (result) =>
                {
                    if (result.Error != null && result.Error is FileNotFoundException)
                    {
                        callback(false, null);
                    }
                    else if (result.Error != null)
                    {
                        callback(false, result.Error);
                    }
                    else
                    {
                        callback(true, null);
                    }
                });
            }
        }

        public static void GetCreationTimeAsync(string path, Action<DateTime, string> callback)
        {
        }

        private static string currentDirectory = @"\";

        public static string GetCurrentDirectory()
        {
            return currentDirectory;
        }

        public static void GetDirectoriesAsync(string path, Action<string[], Exception> callback)
        {
        }

        public static void GetDirectoriesAsync(string path, string searchPattern, Action<string[], Exception> callback)
        {
        }

        public static string GetDirectoryRoot()
        {
            return @"\";
        }

        public static void GetFilesAsync(string path, Action<string[], Exception> callback)
        {
        }

        public static void GetFilesAsync(string path, string searchPattern, Action<string[], Exception> callback)
        {
        }

        public static void GetFileSystemEntriesAsync(string path, Action<AbstractFileSystemInfo[], Exception> callback)
        {
        }

        public static void GetFileSystemEntriesAsync(string path, string searchPattern, Action<AbstractFileSystemInfo[], Exception> callback)
        {
        }

        public static void GetLastAccessTimeAsync(string path, Action<DateTime, Exception> callback)
        {
        }

        public static void GetLastWriteTimeAsync(string path, Action<DateTime, Exception> callback)
        {
        }

        public static void MoveAsync(string sourceDirName, string destDirName, Action<Exception> callback)
        {
        }

        public static void SetCurrentDirectory(string path)
        {
            currentDirectory = path;
        }

        internal static string FixRelativePath(string path)
        {
            if (!path.StartsWith(@"\")) // Doesn't begin with "\" so relative append cwd
                return currentDirectory + (currentDirectory.EndsWith(@"\") ? "" : @"\") + path;
            return path;
        }

        internal static void GetDbxDirInfo(string path, Action<DBoxListing, Exception> callback)
        {
            if (EnsureDbxAppHasInstance((ex) => callback(null, ex)))
            {
                DbxApp.ListDirAndContents(path, new List<string>(), (result) =>
                {
                    if (result.Error != null)
                    {
                        callback(null, result.Error);
                    }
                    else
                    {
                        callback(result.DirInfo, null);
                    }
                });
            }
        }
    }
}